package com.jvmmonitor.service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jvmmonitor.model.ObjectSizeStats;
import com.jvmmonitor.util.ConfigLoader;

/**
 * 对象大小监控服务
 */
public class ObjectSizeMonitor {
    private static final Logger logger = LoggerFactory.getLogger(ObjectSizeMonitor.class);
    
    // 对象大小阈值
    private final long smallObjectThreshold;
    private final long mediumObjectThreshold;
    
    // 小对象统计
    private final AtomicLong smallObjectCount = new AtomicLong(0);
    private final AtomicLong smallObjectTotalSize = new AtomicLong(0);
    
    // 中等对象统计
    private final AtomicLong mediumObjectCount = new AtomicLong(0);
    private final AtomicLong mediumObjectTotalSize = new AtomicLong(0);
    
    // 大对象统计
    private final AtomicLong largeObjectCount = new AtomicLong(0);
    private final AtomicLong largeObjectTotalSize = new AtomicLong(0);
    
    // 总对象统计
    private final AtomicLong totalObjectCount = new AtomicLong(0);
    private final AtomicLong totalObjectSize = new AtomicLong(0);
    
    // 最新的对象大小统计数据
    private volatile ObjectSizeStats latestObjectSizeStats;
    
    // 历史对象大小统计数据
    private List<ObjectSizeStats> objectSizeStatsHistory;
    
    // 历史数据最大数量
    private static final int MAX_HISTORY_SIZE = 100;
    
    /**
     * 构造方法
     */
    public ObjectSizeMonitor() {
        // 从配置中获取对象大小阈值
        this.smallObjectThreshold = ConfigLoader.getSmallObjectThreshold();
        this.mediumObjectThreshold = ConfigLoader.getMediumObjectThreshold();
        this.objectSizeStatsHistory = new ArrayList<>();
        
        logger.info("ObjectSizeMonitor initialized with thresholds: small={}B, medium={}B", 
                smallObjectThreshold, mediumObjectThreshold);
    }
    
    /**
     * 更新对象大小统计
     * @param className 对象类名
     * @param objectSize 对象大小（字节）
     */
    public void updateObjectSizeStats(String className, long objectSize) {
        // 根据对象大小更新相应的计数器
        if (objectSize < smallObjectThreshold) {
            smallObjectCount.incrementAndGet();
            smallObjectTotalSize.addAndGet(objectSize);
        } else if (objectSize < mediumObjectThreshold) {
            mediumObjectCount.incrementAndGet();
            mediumObjectTotalSize.addAndGet(objectSize);
        } else {
            largeObjectCount.incrementAndGet();
            largeObjectTotalSize.addAndGet(objectSize);
        }
        
        // 更新总计数器
        totalObjectCount.incrementAndGet();
        totalObjectSize.addAndGet(objectSize);
    }
    
    /**
     * 收集对象大小统计数据
     */
    public void collectStats() {
        ObjectSizeStats stats = new ObjectSizeStats();
        stats.setTimestamp(System.currentTimeMillis());
        
        // 设置统计数据
        stats.setSmallObjectCount(smallObjectCount.get());
        stats.setSmallObjectTotalSize(smallObjectTotalSize.get());
        stats.setMediumObjectCount(mediumObjectCount.get());
        stats.setMediumObjectTotalSize(mediumObjectTotalSize.get());
        stats.setLargeObjectCount(largeObjectCount.get());
        stats.setLargeObjectTotalSize(largeObjectTotalSize.get());
        stats.setTotalObjectCount(totalObjectCount.get());
        stats.setTotalObjectSize(totalObjectSize.get());
        
        // 更新最新统计数据
        latestObjectSizeStats = stats;
        
        // 添加到历史记录
        addToHistory(stats);
        
        // 记录统计日志
        logObjectSizeStats(stats);
    }
    
    /**
     * 记录对象大小统计日志
     * @param stats 对象大小统计数据
     */
    private void logObjectSizeStats(ObjectSizeStats stats) {
        // 使用结构化的单条日志记录对象大小统计信息，减少日志行数并提高可读性
        // 确保对象数量使用正确的复数形式
        String objectUnit = stats.getTotalObjectCount() == 1 ? " object" : " objects";
        
        String objectSizeInfo = String.format("[OBJECT STATS] Total: %d%s (%s) | " +
                        "Small(<%.0fKB): %d objects (%s, %.1f%%) | " +
                        "Medium(%.0fKB-%.1fMB): %d objects (%s, %.1f%%) | " +
                        "Large(>%.1fMB): %d objects (%s, %.1f%%)",
                stats.getTotalObjectCount(),
                objectUnit,
                formatBytes(stats.getTotalObjectSize()),
                smallObjectThreshold / 1024.0,
                stats.getSmallObjectCount(),
                formatBytes(stats.getSmallObjectTotalSize()),
                stats.getSmallObjectRatio() * 100,
                smallObjectThreshold / 1024.0,
                mediumObjectThreshold / (1024.0 * 1024.0),
                stats.getMediumObjectCount(),
                formatBytes(stats.getMediumObjectTotalSize()),
                stats.getMediumObjectRatio() * 100,
                mediumObjectThreshold / (1024.0 * 1024.0),
                stats.getLargeObjectCount(),
                formatBytes(stats.getLargeObjectTotalSize()),
                stats.getLargeObjectRatio() * 100);
        
        logger.info(objectSizeInfo);
    }
    
    /**
     * 重置统计计数器
     */
    public void resetStats() {
        smallObjectCount.set(0);
        smallObjectTotalSize.set(0);
        mediumObjectCount.set(0);
        mediumObjectTotalSize.set(0);
        largeObjectCount.set(0);
        largeObjectTotalSize.set(0);
        totalObjectCount.set(0);
        totalObjectSize.set(0);
        
        logger.debug("Object size stats counters reset");
    }
    
    /**
     * 获取当前对象大小分布统计
     * @return 包含小、中、大对象数量和大小的数组，格式：[小对象数量, 小对象总大小, 中等对象数量, 中等对象总大小, 大对象数量, 大对象总大小]
     */
    public long[] getCurrentObjectSizeDistribution() {
        return new long[]{
            smallObjectCount.get(),
            smallObjectTotalSize.get(),
            mediumObjectCount.get(),
            mediumObjectTotalSize.get(),
            largeObjectCount.get(),
            largeObjectTotalSize.get()
        };
    }
    
    /**
     * 将对象大小统计数据添加到历史记录
     */
    private synchronized void addToHistory(ObjectSizeStats stats) {
        objectSizeStatsHistory.add(stats);
        
        // 保持历史记录大小不超过最大值
        if (objectSizeStatsHistory.size() > MAX_HISTORY_SIZE) {
            objectSizeStatsHistory.remove(0);
        }
    }
    
    /**
     * 获取最新的对象大小统计数据
     */
    public ObjectSizeStats getLatestObjectSizeStats() {
        return latestObjectSizeStats;
    }
    
    /**
     * 获取对象大小统计历史记录
     */
    public List<ObjectSizeStats> getObjectSizeStatsHistory() {
        return new ArrayList<>(objectSizeStatsHistory);
    }
    
    /**
     * 格式化字节数为可读格式
     * @param bytes 字节数
     * @return 格式化后的字符串
     */
    private String formatBytes(long bytes) {
        if (bytes < 1024) {
            return bytes + "B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.1fKB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.1fMB", bytes / (1024.0 * 1024.0));
        } else {
            return String.format("%.1fGB", bytes / (1024.0 * 1024.0 * 1024.0));
        }
    }
}